package cn.monkey.family.server.domain.shop.item.comment;

import cn.monkey.family.data.Result;
import cn.monkey.family.data.Results;
import cn.monkey.family.data.context.RequestContext;
import cn.monkey.family.data.crud.AbstractCrudService;
import cn.monkey.family.data.shop.item.Item;
import cn.monkey.family.data.shop.item.comment.*;
import cn.monkey.family.server.domain.shop.item.FindItemById;
import com.google.common.base.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.List;
import java.util.Optional;

@Service
public class CommentService extends AbstractCrudService<String, CommentQueryRequest, Comment, CommentDto, CommentVo, CommentMapper, CommentRepository> implements ICommentService {

    private static final Logger log = LoggerFactory.getLogger(CommentService.class);

    final FindItemById findItemById;

    public CommentService(CommentRepository repository,
                          CommentMapper mapper, FindItemById findItemById) {
        super(repository, mapper);
        this.findItemById = findItemById;
    }

    CommentDto trySetCommentOffset(CommentDto commentDto) {
        long lastCommentOffset = this.repository.findLastOffsetByItemIdAndParentId(commentDto.getItemId(), commentDto.getParentId());
        commentDto.setOffset(lastCommentOffset + 1);
        return commentDto;
    }

    @Override
    public Result<CommentVo> create(RequestContext requestContext, CommentDto commentDto) {
        String itemId = commentDto.getItemId();
        if (Strings.isNullOrEmpty(itemId)) {
            log.error("invalid comment queryRequest, itemId is required");
            return Results.fail("ITEM_ID_IS_REQUIRED");
        }
        Optional<Item> itemOptional = this.findItemById.findById(itemId);
        if (itemOptional.isEmpty()) {
            log.error("can not find item by itemId: {}", itemId);
            return Results.fail("INVALID_ITEM_ID");
        }
        String parentId = commentDto.getParentId();
        if (!Strings.isNullOrEmpty(parentId)) {
            Optional<Comment> commentOptional = this.repository.findByParentId(parentId);
            if (commentOptional.isEmpty()) {
                log.error("can not find comment by parentId: {}", parentId);
                return Results.fail("invalid parentId");
            }
        }
        return super.create(requestContext, this.trySetCommentOffset(commentDto));
    }


    @Override
    public Result<Collection<CommentVo>> readTree(RequestContext requestContext,
                                                  CommentQueryRequest queryRequest,
                                                  Sort sort,
                                                  Integer maxDeep) {
        List<Comment> commentList = this.repository.findAllByQueryRequest(queryRequest, sort);
        return Results.ok(this.mapper.toTree(commentList, maxDeep));
    }

    @Override
    public Result<Collection<CommentVo>> readRoot(RequestContext context, CommentQueryRequest queryRequest, Sort sort) {
        String itemId = queryRequest.getItemId();
        if (Strings.isNullOrEmpty(itemId)) {
            log.error("invalid comment queryRequest, itemId is required");
            return Results.fail("ITEM_ID_IS_REQUIRED");
        }
        Optional<Item> itemOptional = this.findItemById.findById(itemId);
        if (itemOptional.isEmpty()) {
            log.error("can not find item by itemId: {}", itemId);
            return Results.fail("INVALID_ITEM_ID");
        }
        List<Comment> commentList = this.repository.findAllByItemIdAndParentIdIsNull(itemId, sort);
        return Results.ok(commentList.stream().map(this.mapper::toVo).toList());
    }
}
